package com.xingkeduo.pojo.table;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xingkeduo.dto.MarketDto;
import com.xingkeduo.dto.payment.PayeeOrderResponseDto;
import com.xingkeduo.dto.payment.ThirdpartyType;
import com.xingkeduo.pojo.enums.*;
import com.xingkeduo.util.pojo.exception.BusinessException;
import com.xingkeduo.utils.DateTimeUtils;
import com.xingkeduo.utils.TableAnnotations;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.hibernate.validator.constraints.Length;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.xingkeduo.utils.DateTimeUtils.yyyy_MM_dd_HH_mm_ss;

/**
 * @author chi  2019-02-13 15:49
 **/

/**
 * `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 * `user_id` int(11) DEFAULT NULL COMMENT '对应t_user表中的id',
 * `wechat_id` int(11) DEFAULT NULL COMMENT '对应t_wechat_account表中的id',
 * `store_id` int(10) unsigned NOT NULL COMMENT '店铺id',
 * `product_id` int(11) DEFAULT NULL COMMENT '商品id',
 * `admin_id` int(11) DEFAULT NULL COMMENT '手艺人ID',
 * `order_no` char(16) NOT NULL COMMENT '订单号',
 * `out_order_no` char(64) DEFAULT NULL COMMENT '微信支付第三方唯一标识 out_order_no（如果是支付宝支付的，就代表支付宝的商户订单号；如果是微信支付的，就代表微信的商户订单号）',
 * `alipay_trade_no` varchar(64) DEFAULT NULL COMMENT '代表支付宝交易号（只有支付宝才会有值）',
 * `all_price` decimal(10,2) NOT NULL DEFAULT '20.00' COMMENT '总金额',
 * `coupon_price` decimal(10,2) NOT NULL COMMENT '使用优惠的金额',
 * `pay_price` decimal(10,2) NOT NULL DEFAULT '20.00' COMMENT '实际支付的金额',
 * `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '-2 => ''已经退款'',    // 已经退款         -1 => ''申请退款'',    // 申请退款          0  => ''等待支付'',    // 未付款，等待支付         1  => ''进行中...'',   // 已经付款，等待理发         2  => ''等待评价'',    // 已经理发，等待评价         3  => ''已完成'',      // 已经完成，等待管理员确认         4  => ''已分享''       // 用户已分享',
 * `type` tinyint(2) NOT NULL DEFAULT '2' COMMENT '1-现金支付（微信代客支付） | 2-微信公众平台支付 | 3-微信扫码支付 | 4-支付宝服务窗支付  | 5-随心付微信支付 | 6-百度糯米 | 7-大众点评 | 8-支付宝扫码支付 | 9-支付宝随心付 | 10-老年票（微信支付） | 11-商品（微信）支付 | 12-商品（支付宝）支付 | 13-老年票（支付宝支付） | 14-支付宝代客支付 | 15-支付宝口碑订单 | 16-支付宝口碑产品 | 17-商品随心付 | 18-洗发随星付 | 19-官网支付宝支付 | 20-官网微信支付 | 21-官网支付宝商品支付 | 22-官网微信商品支付 | （23,24是原来17拆分出来的）23-支付宝商品随心付 | 24-微信商品随心付 | 25-支付宝洗发随心付 | 26-微信洗发随心付 | 27-支付宝小孩代购  | 28-微信小孩代购 29-招行积分 30储值剪发订单 31储值商品订单 32|金色世纪积分 ',
 * `is_print` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0-未打印小票|1-已经打印小票',
 * `remark` varchar(255) NOT NULL COMMENT '订单备注',
 * `paytime` int(10) NOT NULL COMMENT '支付时间',
 * `createtime` int(10) NOT NULL,
 * `createtimestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'date时间',
 * `lastupdate` int(10) NOT NULL,
 * `serve_start_time` int(10) DEFAULT '0' COMMENT '开始服务时间',
 * `serve_end_time` int(10) DEFAULT '0' COMMENT '结束服务时间',
 * `test` tinyint(1) DEFAULT '0' COMMENT '是否测试数据,测试数据上线后删除',
 * `date` int(4) DEFAULT '0' COMMENT '微信公众帐号下单的时间段的小时数（比如：8：00-9：00 保存为8）',
 * `selected_ticket_type` tinyint(1) DEFAULT '1' COMMENT '票类型 1全天票，2限时票',
 * `coupon_detail_id` int(11) DEFAULT NULL COMMENT '卡券id（对应t_coupon_detail表中的f_id）',
 * `service_id` int(11) DEFAULT NULL COMMENT '客服管理的第三方（点评，百度糯米）的记录id',
 * `card_detail_id` int(11) DEFAULT NULL COMMENT '会员卡卡id（对应t_card_log表中的f_id）',
 * `flag` int(11) DEFAULT NULL COMMENT '优惠标识 1优惠券 2会员卡',
 * `is_points` tinyint(1) DEFAULT '0' COMMENT '是否添加积分日志 0未添加 1已添加',
 * `is_send_message` tinyint(1) DEFAULT '1' COMMENT '是否发送过评论消息 0否1是',
 * `product_num` int(10) DEFAULT '0' COMMENT '商品数量（商品下单或者随星付的都要有数量）',
 * `product_ids` varchar(255) DEFAULT NULL,
 * `product_details` longtext COMMENT '商品信息详情（已经序列化）',
 * `hair_id` int(11) DEFAULT NULL COMMENT '发型ID',
 * `mode` tinyint(1) DEFAULT '1' COMMENT '队列类型1现场队列2预约队列（新逻辑中全部是2，此字段不参与统计）',
 * `appointment_time` int(10) DEFAULT NULL COMMENT '预约时间',
 * `expect_time` int(10) DEFAULT '0' COMMENT '期望等待时间',
 * `expiration_time` int(10) DEFAULT '1800' COMMENT '过期时间（默认是30分钟也就是1800秒后，只要用户不用支付就直接过期）',
 * `excel` tinyint(1) DEFAULT NULL,
 * `is_difference_price` tinyint(1) DEFAULT '0' COMMENT '是否有差价 0否 1是',
 * `difference_price` decimal(10,2) DEFAULT NULL COMMENT '差价金额',
 * `difference_price_detail` longtext COMMENT '差价详情 ',
 * `service_type` tinyint(1) DEFAULT '1' COMMENT '服务类型 1剪发 2刘海 3高级',
 * `difference_price_out_order_no` char(64) DEFAULT NULL COMMENT '差价商户订单号',
 * `is_send_pay_message` tinyint(1) DEFAULT '0' COMMENT '0 未发送 1已发送',
 * `reduce_price` decimal(10,2) DEFAULT NULL COMMENT '减免金额（五一活动用）',
 * `refund_reason` varchar(255) DEFAULT NULL COMMENT '退款原因',
 * `modify_once` tinyint(1) DEFAULT '0' COMMENT '预约时间只能修改一次',
 * `activity` int(11) NOT NULL DEFAULT '0' COMMENT '活动,0 无  1 新发型师优惠',
 */

@Slf4j
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName(value = "t_order")
public class Order extends BaseTable<Order> {


    @TableAnnotations("用户id")
    @Length(max = 10, message = "length长度在[5,17]之间")
    private String userId;

    @TableAnnotations("门店id")
    private String storeId;
    @TableAnnotations("门店name")
    private String storeName;

    @TableAnnotations("手艺人ID")
    private String adminId;

    @TableAnnotations("订单号")
    private String orderNo;

    @TableAnnotations("微信支付第三方唯一标识 out_order_no（如果是支付宝支付的，就代表支付宝的商户订单号；如果是微信支付的，就代表微信的商户订单号）")
    private String outOrderNo;

    @TableAnnotations("代表支付宝交易号")
    private String alipayTradeNo;

    @TableAnnotations("总金额")
    private BigDecimal allPrice;

    @TableAnnotations("使用优惠的金额")
    private BigDecimal couponPrice;

    @TableAnnotations("实际支付的金额")
    private BigDecimal payPrice;

    @TableAnnotations("详见 OrderStatus.class")
    private OrderStatus status = OrderStatus.NOT_PAY;

    @TableAnnotations("支付方式")
    private PayType payType;

    @TableAnnotations("订单备注")
    private String remark;

    @TableAnnotations("支付时间")
    private LocalDateTime payTime;

    @TableAnnotations("支付成功")
    private Boolean paySuccess = false;

    @TableAnnotations("开始服务时间")
    private LocalDateTime serveStartTime;

    @TableAnnotations("结束服务时间")
    private LocalDateTime serveEndTime;

    @TableAnnotations("发型ID")
    private int hairId;

    @TableAnnotations("预约开始时间")
    private LocalDateTime appointmentStartTime;

    @TableAnnotations("预约结束时间")
    private LocalDateTime appointmentEndTime;

    /////////////////////////////
    //需要新加的字段
    @TableAnnotations("是否选择发型师")
    private Boolean chooseAdmin;

    @TableAnnotations("预约发型师id")
    private String appointmentAdminId;
    @TableAnnotations("预约发型师name")
    private String appointmentAdminName;


    //微信支付宝或者app支付
    @TableAnnotations("支付渠道")
    private String paymentChannels;

    @TableAnnotations("城市id")
    private String cityId;
    @TableAnnotations("城市name")
    private String cityName;

    @TableAnnotations("分公司id")
    private String branchOfficeId;
    @TableAnnotations("分公司name")
    private String branchOfficeName;

    @TableAnnotations("大区id")
    private String vendorId;
    @TableAnnotations("大区name")
    private String vendorName;

    @TableAnnotations("用户手机号")
    private String userMobile;

    @TableAnnotations("用户昵称")
    private String userNickName;

    @TableAnnotations("用户头像")
    private String userHeadUrl;


    @TableAnnotations("手艺人名称")
    private String adminName;

    @TableAnnotations("服务完成")
    private Boolean serviceDown = false;

    @TableAnnotations("排队号")
    private String waitingLineNo;


    @TableAnnotations("预约时间只能修改一次")
    private Boolean modifyOnce = false;
    /**
     * 订单来源
     */
    @TableAnnotations("订单来源")
    private OrderSource orderSource;

    /**
     * 已评价字段
     */
    @TableAnnotations("已评价")
    private Boolean hadComment;
    /**
     * 门店地址
     */
    @TableAnnotations("门店地址")
    private String storeAddress;


    @TableAnnotations("服务类型Id")
    private String serviceTypeId;

    @TableAnnotations("服务类型名称")
    private String serviceTypeName;

    @TableAnnotations("库存id")
    private String appointmentId;

    @TableAnnotations("随心付类型")
    private GatheringType gatheringType;


    //验票码
    @TableAnnotations("验票码")
    private String ticketCode;

    @TableAnnotations("验票码过期时间")
    private LocalDateTime ticketCodeExpireTime;

    //优惠标识 1优惠券 2会员卡
    private String marketingType;

    //卡券详情
    @TableField(exist = false)
    private String cardCouponDetail;

    //卡券金额
    private BigDecimal marketingPrice;

    //公司补贴金额
    private BigDecimal subsidiesPrice;

    //活动类型
    private String activityType;

    //活动详情
    @TableField(exist = false)
    private String activityDetail;

    //活动金额
    private BigDecimal activityPrice;

    //活动是否是最优组合
    private String optimal;

    //活动id
    private String activityId;

    //卡券id
    private String marketingId;

    @TableAnnotations("代购类型")
    private String payForAnotherTypeId;
    private String payForAnotherTypeName;


    @TableAnnotations("订单标签,逗号分隔")
    private String labels;
    //指定客
    @TableAnnotations("指定客")
    private Boolean designatedCustomer;

    @TableAnnotations("是否是免费卡")
    private Boolean freeCard = false;


    public OrderStatusLog covertStatus(OrderStatus newStatus, OrderAction orderAction) {
        return covertStatus(newStatus, orderAction, null, null, null);
    }

    public OrderStatusLog addOrderAction(OrderAction orderAction) {
        OrderStatusLog orderStatusLog = new OrderStatusLog();
        orderStatusLog.setOrderId(this.id)
                .setNewStatus(this.status)
                .setOldStatus(this.status)
                .setOrderAction(orderAction)
                .setTime(LocalDateTime.now().format(yyyy_MM_dd_HH_mm_ss))
                .setStatus(1);
        return orderStatusLog;
    }

    public OrderStatusLog covertStatus(OrderStatus newStatus, OrderAction orderAction, String modifyId, String modifyName, String remark) {
        log.error("no={}, id={} 尝试更改状态,当前状态{},修改为{},action{}", this.orderNo, this.getId(), this.getStatus(), newStatus, orderAction);
        OrderStatus oldStatus = this.getStatus();
        Boolean covert = this.status.covert(newStatus);
        if (covert) {
            //生成log实体

            this.status = newStatus;

            OrderStatusLog orderStatusLog = new OrderStatusLog();
            orderStatusLog.setOrderId(this.id)
                    .setNewStatus(newStatus)
                    .setOldStatus(oldStatus)
                    .setOrderAction(orderAction)
                    .setTime(LocalDateTime.now().format(yyyy_MM_dd_HH_mm_ss))
                    .setModifyId(modifyId)
                    .setModifyName(modifyName)
                    .setStatus(newStatus.getEndStatus())
                    .setRemark(remark);
            return orderStatusLog;
        }
        log.error("{}更改状态失败,当前状态{},修改为{}", this.orderNo, oldStatus, newStatus);
        throw new BusinessException(BusinessException.Type.DEFAULT, "操作失败");
    }


    /**
     * 订单初始化
     */
    public void init(String orderNo,boolean isRelease) {

        /*
        订单号生成规则：业务类型+日期时间+随机数，共13位
        示例：8190816135732
        8 190816 135732
        业务类型：8 服务，9 零售    6 测试环境
        日期时间：190816 精确到天
        随机数：6位 每天最多100万单
         */

        String a = isRelease ? "8" : "6";
        this.orderNo = a + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd")) + LocalTime.now().getHour() * 4 + 2 + orderNo;
        this.chooseAdmin = true;
    }

    /**
     * 初始化验票码
     *
     * @param no
     */
    public void initTicketcode(String no) {
        this.ticketCode = no;
        if (freeCard) {
            this.ticketCodeExpireTime = LocalDateTime.now().plusSeconds(25L);
        }else {
            this.ticketCodeExpireTime = LocalDateTime.now().plusYears(10L);
        }
    }

    /**
     * 支付成功
     */
    public void paid(PayeeOrderResponseDto payeeOrderResponseDto, String waitingLineNo,String ticketCode) {
        if (StringUtils.isNotBlank(waitingLineNo)) {
            this.waitingLineNo = "A" + waitingLineNo;
        }
        this.payTime = payeeOrderResponseDto.getPayTime();
        this.paymentChannels = payeeOrderResponseDto.getPayType().toString();
        this.paySuccess = true;
        ThirdpartyType thirdpartyType = payeeOrderResponseDto.getPayType();
        this.payType = PayType.covertThirdpartyType(thirdpartyType);
        initTicketcode(ticketCode);
    }



    /**
     * 退款日期校验
     *
     * @return
     */
    public boolean checkRefund(RefundType refundType) {

        if (OrderStatus.REFUND_DONE.equals(this.getStatus())) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单已退款");
        }

        switch (refundType) {
            case USER: {
                if (serviceDown) {
                    throw new BusinessException(BusinessException.Type.DEFAULT, "服务已完成,不能退款,请联系客服");
                }
                if (OrderStatus.IN_SERVICE.equals(status)) {
                    throw new BusinessException(BusinessException.Type.DEFAULT, "服务已开始,不能退款,请联系客服");
                }
                break;
            }
            case ADMIN: {
                break;
            }
            case BACKGROUND: {
                break;
            }
        }

        LocalDateTime createdTime = this.getPayTime();
        LocalDateTime now = LocalDateTime.now();
        Duration duration = Duration.between(createdTime, now);
        long l = duration.toDays();
        if (l > 90) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "退款时间超过90天,请联系客服");
        }
        return true;
    }


    /**
     * 以下非数据库字段
     */
    @TableField(exist = false)
    private String statusName;

    @TableField(exist = false)
    private String gatheringTypeName;
    //代购或者随行付
    @TableField(exist = false)
    private String orderLabel;
    @TableField(exist = false)
    private String payTypeName;
    @TableField(exist = false)
    private String orderSourceName;

    //发型师头像
    @TableField(exist = false)
    private String adminAvatar;

    //发型师工号
    @TableField(exist = false)
    private String adminCode;

    //发型师工号
    @TableField(exist = false)
    private String adminNickName;

    //预约发型师头像
    @TableField(exist = false)
    private String appointmentAdminAvatar;

    //预约发型师工号
    @TableField(exist = false)
    private String appointmentAdminCode;
    @TableField(exist = false)
    private String appointmentAdminNickName;
    @TableAnnotations("预约发型师name")
    @TableField(exist = false)
    private String appointmentAdminMobile;


    public String getStatusName() {
        return this.status.getValue();
    }


    public String getGatheringTypeName() {
        return this.gatheringType == null ? null : this.gatheringType.getValue();
    }

    public String getOrderLabel() {
        if (orderSource != null) {
            switch (this.orderSource) {
                case SUI_XING_FU:
                    return orderSource.getName();
                case PAY_FOR_ANOTHER:
                    return payForAnotherTypeName;
            }
        }
        return "";
    }

    public String getPayTypeName() {
        return this.payType == null ? null : this.payType.getValue();
    }

    public String getOrderSourceName() {
        return this.orderSource.getName();
    }


    /**
     * todo chi
     * 消息往微信还是支付宝推送
     *
     * @return
     */
    public PayType messageChannel() {
        int name = this.getPayType().getKey();
        if (1 == name) {
            return PayType.ALIPAY;
        } else {
            return PayType.WECHAT;
        }
    }

}
